home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / cug105 / floatxt.c < prev    next >
Text File  |  1984-06-05  |  9KB  |  405 lines

  1.  
  2.  
  3. /*
  4.     Floating point package support routines
  5.  
  6.     Note the "fp" library function, available in DEFF2.CRL,
  7.     is used extensively by all the floating point number
  8.     crunching functions.
  9.  
  10.     (see FLOAT.DOC for details...)
  11.  
  12.     NEW FEATURE: a special "printf" function has been included
  13.              in this source file for use with floating point
  14.              operands, in addition to the normal types. The
  15.              printf presented here will take precedence over
  16.              the DEFF.CRL version when "float" is specified
  17.              on the CLINK command line at linkage time.
  18.              Note that the "fp" function, needed by most of
  19.              the functions in this file, resides in DEFF2.CRL
  20.              and will be automatically collected by CLINK.
  21.  
  22.     All functions here written by Bob Mathias, except printf and
  23.     _spr (written by Leor Zolman.)
  24.  
  25.     New Functions Added    fpmag converts to floating magnitude
  26.                   fpchs changes sign of floating point no
  27.                   fpasg provides assignment of fl pt no
  28.                   ftoit converts fl pt no to trunc. int.
  29.                   ftoir converts fl pt no to rounded int.
  30.  
  31.                 written by L. C. Calhoun
  32.  
  33. */
  34.  
  35. #include "bdscio.h"
  36.  
  37. #define NORM_CODE    0
  38. #define ADD_CODE    1
  39. #define SUB_CODE    2
  40. #define MULT_CODE    3
  41. #define DIV_CODE    4
  42. #define FTOA_CODE    5
  43. #define EXPON_SIGN    0x80   /* break point for exponent sign */
  44.  
  45. fpcomp(op1,op2)
  46.     char *op1,*op2;
  47. {
  48.     char work[5];
  49.     fpsub(work,op1,op2);
  50.     if (work[3] > 127) return (-1);
  51.     if (work[0]+work[1]+work[2]+work[3]) return (1);
  52.     return (0);
  53. }
  54.  
  55. fpnorm(op1) char *op1;
  56. {    fp(NORM_CODE,op1,op1);return(op1);}
  57.  
  58. fpadd(result,op1,op2)
  59.     char *result,*op1,*op2;
  60. {    fp(ADD_CODE,result,op1,op2);return(result);}
  61.  
  62. fpsub(result,op2,op1)
  63.     char *result,*op1,*op2;
  64.     {fp(SUB_CODE,result,op1,op2);return(result);}
  65.  
  66. fpmult(result,op1,op2)
  67.     char *result,*op1,*op2;
  68. {    fp(MULT_CODE,result,op1,op2);
  69.     return (result);
  70. }
  71.  
  72. fpdiv(result,op1,op2)
  73.     char *result,*op1,*op2;
  74. {    fp(DIV_CODE,result,op1,op2);return(result);}
  75.  
  76. atof(fpno,s)
  77.     char fpno[5],*s;
  78. {
  79.     char *fpnorm(),work[5],ZERO[5],FP_10[5];
  80.     int sign_boolean,power;
  81.  
  82.     initb(FP_10,"0,0,0,80,4");
  83.     setmem(fpno,5,0);
  84.     sign_boolean=power=0;
  85.  
  86.     while (*s==' ' || *s=='\t') ++s;
  87.     if (*s=='-'){sign_boolean=1;++s;}
  88.     for (;isdigit(*s);++s){
  89.         fpmult(fpno,fpno,FP_10);
  90.         work[0]=*s-'0';
  91.         work[1]=work[2]=work[3]=0;work[4]=31;
  92.         fpadd(fpno,fpno,fpnorm(work));
  93.     }
  94.     if (*s=='.'){
  95.         ++s;
  96.         for (;isdigit(*s);--power,++s){
  97.             fpmult(fpno,fpno,FP_10);
  98.             work[0]=*s-'0';
  99.             work[1]=work[2]=work[3]=0;work[4]=31;
  100.             fpadd(fpno,fpno,fpnorm(work));
  101.         }
  102.     }
  103.     if (toupper(*s) == 'E') {++s; power += atoi(s); }
  104.     if (power>0)
  105.         for (;power!=0;--power) fpmult(fpno,fpno,FP_10);
  106.     else
  107.     if (power<0)
  108.         for (;power!=0;++power) fpdiv(fpno,fpno,FP_10);
  109.     if (sign_boolean){
  110.         setmem(ZERO,5,0);
  111.         fpsub(fpno,ZERO,fpno);
  112.     }
  113.     return(fpno);
  114. }
  115. ftoa(result,op1)
  116.     char *result,*op1;
  117. {    fp(FTOA_CODE,result,op1);return(result);}
  118.  
  119. itof(op1,n)
  120. char *op1;
  121. int n;
  122. {
  123.     char temp[20];
  124.     return atof(op1, itoa(temp,n));
  125. }
  126.  
  127. itoa(str,n)
  128. char *str;
  129. {
  130.     char *sptr;
  131.     sptr = str;
  132.     if (n<0) { *sptr++ = '-'; n = -n; }
  133.     _uspr(&sptr, n, 10);
  134.     *sptr = '\0';
  135.     return str;
  136. }
  137.  
  138.  
  139. /*
  140.     The short "printf" function given here is exactly the
  141.     same as the one in the library, but it needs to be placed
  142.     here so that the special "_spr" is used instead of the
  143.     normal one in DEFF.CRL. The way the linker works is that
  144.     a function is not linked in UNTIL IT IS REFERENCED...so
  145.     if the definition of "printf" were not placed here in this
  146.     file, "_spr" would not be referenced at all
  147.     until the "printf" from DEFF.CRL got yanked in, at which time
  148.     "_spr" would ALSO be taken from DEFF.CRL and cause the
  149.     floating point "_spr" options to not be recognized.
  150.  
  151.     In other words, if "printf" were not given explicitly here,
  152.     the WRONG _spr would end up being used.
  153. */
  154.  
  155.  
  156. printf(format)
  157. char *format;
  158. {
  159.     char line[MAXLINE];
  160.     _spr(line,&format);    /* use "_spr" to form the output */
  161.     puts(line);        /* and print out the line     */
  162. }
  163.  
  164.  
  165. /*
  166.     This is the special formatting function, which supports the
  167.     "e" and "f" conversions as well as the normal "d", "s", etc.
  168.     When using "e" or "f" format, the corresponding argument in
  169.     the argument list should be a pointer to one of the five-byte
  170.     strings used as floating point numbers by the floating point
  171.     functions. Note that you don't need to ever use the "ftoa"
  172.     function when using this special printf/sprintf combination;
  173.     to achieve the same result as ftoa, a simple "%e" format
  174.     conversion will do the trick. "%f" is used to eliminate the
  175.     scientific notation and set the precision. The only [known]
  176.     difference between the "e" and "f" conversions as used here
  177.     and the ones described in the Kernighan & Ritchie book is that
  178.     ROUNDING does not take place in this version...e.g., printing
  179.     a floating point number which happens to equal exactly 3.999
  180.     using a "%5.2f" format conversion will produce " 3.99" instead
  181.     of " 4.00".
  182. */
  183.  
  184.  
  185. _spr(line,fmt)
  186. char *line, **fmt;
  187. {
  188.     char _uspr(), c, base, *sptr, *format;
  189.     char wbuf[MAXLINE], *wptr, pf, ljflag;
  190.     int width, precision, exp, *args;
  191.  
  192.     format = *fmt++;    /* fmt first points to the format string */
  193.     args = fmt;        /* now fmt points to the first arg value */
  194.     while (c = *format++)
  195.       if (c == '%') {
  196.         wptr = wbuf;
  197.         precision = 6;
  198.         ljflag = pf = 0;
  199.  
  200.         if (*format == '-') {
  201.             format++;
  202.             ljflag++;
  203.          }
  204.  
  205.         if ( !(width = _gv2(&format))) width++;
  206.  
  207.         if ((c = *format++) == '.') {
  208.             precision = _gv2(&format);
  209.             pf++;
  210.             c = *format++;
  211.          }
  212.  
  213.         switch(toupper(c)) {
  214.         case 'E':  if (precision>7) precision = 7;
  215.                ftoa(wbuf,*args++);
  216.                strcpy(wbuf+precision+3, wbuf+10);
  217.                width -= strlen(wbuf);
  218.                goto pad2;
  219.  
  220.         case 'F':  ftoa(&wbuf[60],*args++);
  221.                sptr = &wbuf[60];
  222.                while ( *sptr++ != 'E')
  223.                 ;
  224.                exp = atoi(sptr);
  225.                sptr = &wbuf[60];
  226.                if (*sptr == ' ') sptr++;
  227.                if (*sptr == '-') {
  228.                 *wptr++ = '-';
  229.                 sptr++;
  230.                 width--;
  231.                 }
  232.                sptr += 2;
  233.  
  234.                if (exp < 1) {
  235.                 *wptr++ = '0';
  236.                 width--;
  237.                 }
  238.  
  239.                pf = 7;
  240.                while (exp > 0 && pf) {
  241.                 *wptr++ = *sptr++;
  242.                 pf--;
  243.                 exp--;
  244.                 width--;
  245.                 }
  246.  
  247.                while (exp > 0) {
  248.                 *wptr++ = '0';
  249.                 exp--;
  250.                 width--;
  251.                 }
  252.  
  253.                *wptr++ = '.';
  254.                width--;
  255.  
  256.                while (exp < 0 && precision) {
  257.                 *wptr++ = '0';
  258.                 exp++;
  259.                 precision--;
  260.                 width--;
  261.                 }
  262.  
  263.                while (precision && pf) {
  264.                 *wptr++ = *sptr++;
  265.                 pf--;
  266.                 precision--;
  267.                 width--;
  268.                 }
  269.  
  270.                while (precision>0) {
  271.                 *wptr++ = '0';
  272.                 precision--;
  273.                 width--;
  274.                 }
  275.  
  276.                goto pad;
  277.  
  278.  
  279.         case 'D':  if (*args < 0) {
  280.                 *wptr++ = '-';
  281.                 *args = -*args;
  282.                 width--;
  283.                 }
  284.         case 'U':  base = 10; goto val;
  285.  
  286.         case 'X':  base = 16; goto val;
  287.  
  288.         case 'O':  base = 8;
  289.  
  290.              val:  width -= _uspr(&wptr,*args++,base);
  291.                goto pad;
  292.  
  293.         case 'C':  *wptr++ = *args++;
  294.                width--;
  295.                goto pad;
  296.  
  297.         case 'S':  if (!pf) precision = 200;
  298.                sptr = *args++;
  299.                while (*sptr && precision) {
  300.                 *wptr++ = *sptr++;
  301.                 precision--;
  302.                 width--;
  303.                 }
  304.  
  305.              pad:  *wptr = '\0';
  306.              pad2: wptr = wbuf;
  307.                if (!ljflag)
  308.                 while (width-- > 0)
  309.                     *line++ = ' ';
  310.  
  311.                while (*line = *wptr++)
  312.                 line++;
  313.  
  314.                if (ljflag)
  315.                 while (width-- > 0)
  316.                     *line++ = ' ';
  317.                break;
  318.  
  319.          default:  *line++ = c;
  320.  
  321.          }
  322.       }
  323.       else *line++ = c;
  324.  
  325.     *line = '\0';
  326. }
  327. /*  NEW FUNCTIONS ADDED */
  328. /*  new function to convert floating to truncated integer */
  329. ftoit(fpno)
  330. char *fpno;
  331. {
  332.     char *ftoa(), temp[20], temp2[20], *sptr, *wptr;
  333.     int atoi(), exp, pf;
  334.     wptr = &temp2;
  335.     ftoa(temp,fpno);
  336.     sptr=&temp;
  337.     while (*sptr++ != 'E');
  338.     exp = atoi(sptr);
  339.     sptr = &temp;
  340.      if (*sptr == ' ') sptr++;
  341.      if (*sptr == '-')
  342.       {
  343.        *wptr++ = '-'; sptr++;
  344.       }
  345.     sptr += 2;
  346.  
  347.      if (exp < 1 ) *wptr++ = '0';
  348.  
  349.      pf = 7;
  350.      while (exp > 0 && pf)
  351.       {
  352.        *wptr++ = *sptr++;
  353.        pf--; exp--;
  354.       }
  355.      while (exp > 0)
  356.       {
  357.        *wptr++ = '0'; exp--;
  358.       }
  359.      *wptr++ = '.';
  360. /* foregoing lifted from _spr with F format  */
  361.     return ( atoi (temp2) );
  362. }
  363.  
  364. /* new function to round, then convert to integer */
  365. ftoir(fpno)
  366. char *fpno;
  367. {
  368.     char *fpsub(), *fpadd();
  369.     char *atof(), rnd[5], res[5];
  370.     int ftoit();
  371.     atof(rnd,"0.5");
  372.      if (fpno[3] > 127) fpsub(res, fpno, rnd); else
  373.         fpadd(res,fpno,rnd);
  374.     return (ftoit (res));
  375. }
  376.  
  377. /* new function to produce the unsigned magnitude of a fp no. */
  378. char *fpmag(result,fpno)
  379. char *result,*fpno;
  380. {
  381.     char *fpchs();
  382.     if (fpno[3] < 128) return(fpasg(result,fpno));
  383.     else return (fpchs(result,fpno));
  384. }
  385.  
  386. /* new function to change sign of floating point number */
  387. char *fpchs(result,fpno)
  388. char *result,*fpno;
  389. {
  390.     char *fpmult(),minusone[5];
  391.     initb(minusone,"0,0,0,192,1");
  392.     return ( fpmult(result,minusone,fpno) );
  393. }
  394.  
  395. /* a new function to assign <in essence> the value of one
  396.    floating point number to another  */
  397. char *fpasg(result,fpno)
  398. char *result, *fpno;
  399. {
  400.     int index;
  401.     for ( index=0; index <= 4; index++)
  402.         result[index] = fpno[index];
  403.     return (result);
  404. }
  405.